﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace ObjRec
{
    public static class ExternalFunctions
    {
        public const int IMAGE_SIZE = 1080;
        public const double SCALE_FACTOR = 1.3;
        public const int MIN_NEIGHBOR = 3;
        public const int MIN_FACESIZE = 250;
        public const int MAX_FACE_SIZE = int.MaxValue;
        public const int RESCALED_FACE_SIZE = 64;

        public const int LBP_RADIUS = 1;
        public const int LBP_NEIGHBOR = 8;
        public const int LBP_GRID_X = 8;
        public const int LBP_GRID_Y = 8;
        public const int LBP_THRESHOLD = 60;

        //Must not be empty
        public static string[] SUPPORTED_IMAGE_TYPE = { ".jpg", ".jpeg", ".bmp", ".png", ".tiff", ".gif", ".ppm", ".pgm", ".tif" };

        /// <summary>
        /// Clamp value between min and max. If value is greater than max, return max. If value is lower than min. Otherwise, return value
        /// </summary>
        /// <param name="value">Value to be clamped</param>
        /// <param name="min">Minimum value</param>
        /// <param name="max">Maximum value</param>
        /// <returns>int</returns>
        public static int Clamp(int value, int min, int max)
        {
            if (value < min) return min;
            else if (value > max) return max;
            else return value;
        }

        /// <summary>
        /// Get path of folder contains .exe file
        /// </summary>
        public static string GetPath
        {
            get
            {
                return System.Windows.Forms.Application.StartupPath.Replace(@"\\",@"\");
            }
        }

        /// <summary>
        /// COnvert bitmap to byte array
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns>byte[]</returns>
        public static byte[] BitmapToBytes(Bitmap bmp)
        {
            byte[] bytes;
            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, ImageFormat.Bmp);
            bytes = new byte[ms.Length];
            ms.ToArray().CopyTo(bytes, 0);
            ms.Flush();
            ms.Close();
            return bytes;
        }

        /// <summary>
        /// Convert byte array to bitmap
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns>Bitmap</returns>
        public static Bitmap BytesToBitmap(byte[] bytes)
        {
            MemoryStream ms = new MemoryStream(bytes);
            Bitmap bmp = new Bitmap(ms);
            ms.Flush();
            ms.Close();
            return bmp;
        }

        /// <summary>
        /// Check if n is uniform (not greater than 2 bit transitions)
        /// </summary>
        /// <param name="n"></param>
        /// <returns>Bool</returns>
        public static bool isUniform(int n)
        {
            int a = n >> 1;
            int b = a ^ n;
            string s = Convert.ToString(b, 2).PadLeft(LBP_NEIGHBOR, '0').Substring(1);
            return s.Count(c => c == '1') <= 2;
        }

        /// <summary>
        /// Count number of uniforms
        /// </summary>
        /// <param name="numberOfBits">Number of bits</param>
        public static int CountUniform(int numBit)
        {
            int numUniform = 0;
            for (int i = 0; i < Math.Pow(2, numBit); i++)
            {
                if (isUniform(i)) numUniform++;
            }
            return numUniform;
        }

        public static Bitmap OpenImage(string path)
        {
            string ext = System.IO.Path.GetExtension(path);
            Bitmap bmp = null;
            try
            {
                switch (ext.ToLower())
                {
                    case ".pgm":
                        bmp = PGMConverter.ToBitmap(path);
                        break;
                    case ".ppm":
                        bmp = PPMConverter.ReadBitmapFromPPM(path);
                        break;
                    default:
                        bmp = new Bitmap(path);
                        break;
                }
            }
            catch (Exception) { }
            return bmp;
        }
    }
}
